//*****************************************************************************
//
// ssi_handler.c - This file contains the function used to transfer data via
//                 the Stellaris SSI port.
//
// Copyright (c) 2006-2007 Luminary Micro, Inc.  All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 323 of the Stellaris boot loader.
//
//*****************************************************************************

#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_sysctl.h"
#include "gpio.h"
#include "hw_ssi.h"
#include "hw_gpio.h"
#include "boot_loader.h"

//*****************************************************************************
//
//! \addtogroup ssi_handler_src SSI Handler APIs
//! This section describes the functions that are responsible for handling the
//! data transfer over the SSI port.
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
//! This is the number of bits per transfer for SSI.  This is a constant and
//! cannot be changed without corresponding code changes.
//
//*****************************************************************************
#define DATA_BITS_SSI           (8)

//*****************************************************************************
//
//! Sends data via the SSI port in slave mode.
//!
//! \param pucData is the location of the data to send through the SSI port.
//! \param ucSize is the number of bytes of data to send.
//!
//! This function sends data through the SSI port in slave mode.  This function
//! will not return until all bytes are sent.
//!
//! \return This function always returns zero.
//
//*****************************************************************************
int
SendDataSSISlave(unsigned char const *pucData, unsigned char ucSize)
{
    volatile unsigned char ucDevNull;

    //
    // Send the requested number of bytes over the SSI Port.
    //
    while(ucSize)
    {
        //
        // While the receive FIFO is not empty, empty it.
        //
        if(HWREG(SSI_BASE + SSI_O_SR) & SSI_SR_RNE)
        {
            ucDevNull = HWREG(SSI_BASE + SSI_O_DR);
        }

        //
        // While the transmit FIFO is not full, add data to the FIFO.
        //
        if(HWREG(SSI_BASE + SSI_O_SR) & SSI_SR_TNF)
        {
            //
            // Receive one byte for every one that is sent.
            //
            HWREG(SSI_BASE + SSI_O_DR) = *pucData++;
            ucDevNull = HWREG(SSI_BASE + SSI_O_DR);
            ucSize--;
        }
    }

    //
    // All data was sent successfully.
    //
    return(0);
}

//*****************************************************************************
//
//! Receives data from the SSI port in slave mode.
//!
//! \param pucData is the location to store the data received from the SSI
//!     port.
//! \param ucSize is the number of bytes of data to receive.
//!
//! This function receives data from the SSI port in slave mode.  The function
//! will not return until ucSize number of bytes have been received.
//!
//! \return This function always returns zero.
//
//*****************************************************************************
int
ReceiveDataSSISlave(unsigned char *pucData, unsigned char ucSize)
{
    //
    // Ensure that we are sending out zeros so that we don't confuse the host.
    //
    HWREG(SSI_BASE + SSI_O_DR) = 0;

    //
    // Wait for the requested number of bytes.
    //
    while(ucSize)
    {
        //
        // If the FIFO is not empty, then get a byte from the FIFO.
        //
        if(HWREG(SSI_BASE + SSI_O_SR) & SSI_SR_RNE)
        {
            *pucData++ = HWREG(SSI_BASE + SSI_O_DR);
            ucSize--;
        }
    }

    //
    // All bytes have been received correctly.
    //
    return(0);
}

//*****************************************************************************
//
//! Configures the SSI port for slave operation.
//!
//! This function configures the SSI port as a slave and prepares it to
//! transmit/receive data from a SSI master device.
//!
//! \return None.
//
//*****************************************************************************
#if 0
void
SSIConfig(void)
{
    //
    // Enable UART 0.
    //
    HWREG(SYSCTL_RCGC1) = SYSCTL_SET1_SSI;

    //
    // Make the pin(s) be peripheral controlled.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_DIR) = 0;
    HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) = SSI_PINS;

    //
    // Set the output drive strength.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_DR2R) = SSI_PINS;
    HWREG(GPIO_PORTA_BASE + GPIO_O_DR4R) = 0;
    HWREG(GPIO_PORTA_BASE + GPIO_O_DR8R) = 0;
    HWREG(GPIO_PORTA_BASE + GPIO_O_SLR) = 0;

    //
    // Set the SSI device as a slave.
    //
    HWREG(SSI_BASE + SSI_O_CR1) = SSI_CR1_MS;

    //
    // Set the SSI protocol to Motorola with default clock high and data
    // valid on the rising edge.
    //
    HWREG(SSI_BASE + SSI_O_CR0) = (SSI_CR0_SPH | SSI_CR0_SPO |
                                   (DATA_BITS_SSI - 1));
    //
    // Enable the SSI interface.
    //
    HWREG(SSI_BASE + SSI_O_CR1) |= SSI_CR1_SSE;
}
#endif

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************




